如何设计一个iOS统一持久化SDK

设计一个统一持久化SDK的意义

提高可维护性和安全性。
没有统一的存储层,业务代码里存储功能会有很多重复代码,不仅维护性差、安全性也无法保障

提高存储质量和性能。
不同业务场景适合使用的存储方式是不一样的,为了提高性能我们得使用复合式的存储策略,为了保证稳定性还得考虑监控

不同场景的存储方式

KV存储

kV存储是最常用的存储方式,超过80%的业务存储会用到,它是一种NoSQL(非关系型数据库)模型搜索,适用于非复杂业务关系的场景。KV存储又包含5种类型分别是内存KV、文件KV、数据库KV、二级索引KV、流式大文件KV。

内存KV

内存KV是在内存上存储,也是最快速的存储方式,通常文件KV、数据库KV也会实现内存KV进行对象级别的加速。
内存KV的实现要考虑几个关键点,接口设计、清理机制、淘汰机制、并发管理。

淘汰机制
具体实现上建议使用LRU淘汰机制,它的核心思想是“最近用到的数据被重用的概率是最高的”,因此我们需要对缓存进行排序,并且保证位置调整的高性能,很自然地我们会想到使用双向链表来实现。查找一个链表中元素的时间复杂度是O(n),每次命中的时候,我们就需要花费O(n)的时间来进行查找,如果不添加其他的数据结构,这个就是我们能实现的最高效率了。我们还可以组合上hash表,它查找时间复杂度是O(1)。
最后我们可以设计一个数据结构,里面包含一个hashmap和双向链表,使用hashmap查询cache,使用双向链表做排列和位置管理。

清理机制
手机设备内存是奢侈品,在内存紧张时,我们要有清理缓存的机制

并发管理
为了保证多线程调用的安全性,增删改查每项操作我们都要加锁

数据库KV

数据大小在20K~30k以内,使用数据库存储效率较高,数据库KV的安全保障,要支持数据库级别的加密。

文件KV

数据大小大雨20K~30k,适合使用文件KV,需要提供文件校验、加密能力。

二级索引KV

在文件KV的基础上,使用两个key来指定一个value,适合图片库这种需要基于图片url和尺寸信息的场景。

流式文件KV

针对视频等较大的流式文件,如果我们对整块数据进行存取会消耗大量内存,需要进行分段处理。

ORM存储

ORM是对象关系映射Object Relational Mapping,它的核心是将复杂的数据结构对象化,将sql操作转化为简单易用的的面向对象操作。
ORM的开发需要考虑到各种feature,多线程安全、事务、时间模型、列级加密、支持批处理操作、对象域,支持对对象管理方式的控制等。

DB储存

需要进行复杂数据的操作的存储场景,一般就要直接用到DB,DB的设计是一门大学问,要考虑的要点有很多。比如线程池管理、读写互斥、并发控制、任务调度,数据库的加密,Api的易用(SQLite3难用)。其中SQLite3免费版不支持加密的,但它是有预留加密数据库的接口,可以自己实现加密功能。如果要追求极致的性能,在SQL的查询还可以做缓存功能。

执行计划缓存

SQL响应时间包括两部分:RT = 解析时间和 + 执行时间。
如果将执行计划进行缓存可以减少解析的时间,如果将结果集进行缓存,可以减少执行时间。But,由于查询的结果集可能很多,而且数据精彩会被修改,结果集缓存意义不大,因此我们主要考虑对执行计划进行缓存。

相识的sql可以使用同一个执行计划,比如“select from t where num=1”和“select from t where num=2”。因此我们可以先将语句标准化(忽略大小写,忽略空格数目,将常量全部抽象成 ?),减少缓存数量,最后还要考虑淘汰机制,整体思路如下。
1对SQL进行词法语法分析,抽象出常量
2查询执行计划缓存是否命中,若不命中,则进行解析
3将常量绑定到执行计划

监控

TODO

Blacktea wechat
ex. subscribe to my blog by scanning my public wechat account
记录生活于感悟,您的支持将鼓励我继续创作!